/*
 * Copyright (C) 2021 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.xuexiang.xui_lib.component.banner;

import ohos.agp.components.AttrHelper;
import ohos.agp.components.AttrSet;
import ohos.agp.components.BaseItemProvider;
import ohos.agp.components.Component;
import ohos.agp.components.ComponentContainer;
import ohos.agp.components.DirectionalLayout;
import ohos.agp.components.Image;
import ohos.agp.components.ListContainer;
import ohos.agp.components.RecycleItemProvider;
import ohos.agp.components.StackLayout;
import ohos.agp.components.TableLayout;
import ohos.agp.components.element.Element;
import ohos.agp.components.element.ShapeElement;
import ohos.agp.utils.Color;
import ohos.app.Context;
import ohos.eventhandler.EventHandler;
import ohos.eventhandler.EventRunner;
import ohos.eventhandler.InnerEvent;

import com.xuexiang.xui_lib.util.Log;

/**
 * 使用RecyclerView实现轮播Banner
 *
 * @since 2021-04-19
 */
public class BannerLayout extends StackLayout {
    private static final int WHAT_AUTO_PLAY = 1000;
    private static final int DEFAULT_DURATION = 4000;
    private static final int DEFAULT_SPACE = 10;
    private static final float DEFAULT_SCALE = 1.2f;
    private static final int DEFAULT_INDICATOR_SIZE = 5;
    private static final int DEFAULT_INDICATOR_MARGIN = 4;
    private static final int DEFAULT_MARGIN_START = 16;
    private static final int DEFAULT_MARGIN_BOTTOM = 11;
    private static final int DEFAULT_BANNER_SIZE = 11;
    private static final int DEFAULT_GRAVITY = 2;
    private static final int OVER_SCROLL_PERCENT = 40;
    private static final float OVER_SCROLL_RATE = 0.6f;
    private static final int REMAIN_VISIBLE_PERCENT = 20;
    private ListContainer mIndicatorContainer;
    private IndicatorAdapter mIndicatorAdapter;
    private int mIndicatorMargin = DEFAULT_INDICATOR_MARGIN;
    private Element mSelectedDrawable;
    private Element mUnselectedDrawable;

    private ListContainer mRecyclerView;
    private boolean isHasInit;
    private int mBannerSize = DEFAULT_BANNER_SIZE;
    private int mCurrentIndex;
    private boolean mIsPlaying = false;

    private boolean mIsAutoPlaying = true;
    private int mAutoPlayDuration = DEFAULT_DURATION;
    private int marginStart = DEFAULT_MARGIN_START;
    private int marginEnd = 0;
    private int marginBottom = DEFAULT_MARGIN_BOTTOM;
    private int orientation = Component.HORIZONTAL;
    int indicatorSize = DEFAULT_INDICATOR_SIZE;
    private boolean isShowIndicator = true;
//    private int mItemSpace;
//    private float mCenterScale = DEFAULT_SCALE;
//    private float mMoveSpeed = 1.0f;
    private Context context;
    private OnIndicatorIndexChangedListener mOnIndicatorIndexChangedListener;
    private EventHandler mHandler;

    /**
     * 构造方法
     *
     * @param context 上下文
     */
    public BannerLayout(Context context) {
        this(context, null);
    }

    /**
     * 构造方法
     *
     * @param context 上下文
     * @param attrs 属性资源
     */
    public BannerLayout(Context context, AttrSet attrs) {
        this(context, attrs, "");
    }

    /**
     * 构造方法
     *
     * @param callContext 上下文
     * @param attrs 属性资源
     * @param styleName 风格名称
     */
    public BannerLayout(Context callContext, AttrSet attrs, String styleName) {
        super(callContext, attrs, styleName);
        this.context = callContext;
        initView(attrs);
        mHandler = new EventHandler(EventRunner.create(true)) {
            @Override
            protected void processEvent(InnerEvent event) {
                super.processEvent(event);
                if (event.eventId == WHAT_AUTO_PLAY) {
                    if (mCurrentIndex == mRecyclerView.getSelectedItemIndex()) {
                        ++mCurrentIndex;
                        mHandler.sendEvent(WHAT_AUTO_PLAY, mAutoPlayDuration);
                        runMainThread(() -> {
                            mRecyclerView.scrollTo(mCurrentIndex);
                            refreshIndicator();
                        });
                    }
                }
            }
        };
    }

    /**
     * 切换任务到主线程执行
     *
     * @param runnable 执行的runnable
     */
    public void runMainThread(Runnable runnable) {
        EventRunner eventRunner = EventRunner.getMainEventRunner();
        EventHandler eventHandler = new EventHandler(eventRunner);
        eventHandler.postSyncTask(runnable);
    }

    /**
     * 初始化view
     *
     * @param attrs 属性对象
     */
    protected void initView(AttrSet attrs) {
        if (attrs != null) {
            if (attrs.getAttr("bl_showIndicator").isPresent()) {
                isShowIndicator = attrs.getAttr("bl_showIndicator").get().getBoolValue();
            }
            if (attrs.getAttr("bl_interval").isPresent()) {
                mAutoPlayDuration = attrs.getAttr("bl_interval").get().getIntegerValue();
            }
            if (attrs.getAttr("bl_autoPlaying").isPresent()) {
                mIsAutoPlaying = attrs.getAttr("bl_autoPlaying").get().getBoolValue();
            }
            //mItemSpace = px2vp(DEFAULT_SPACE);
            if (attrs.getAttr("bl_itemSpace").isPresent()) {
               // mItemSpace = attrs.getAttr("bl_itemSpace").get().getDimensionValue();
            }
            if (attrs.getAttr("bl_centerScale").isPresent()) {
                //mCenterScale = attrs.getAttr("bl_centerScale").get().getFloatValue();
            }
            if (attrs.getAttr("bl_moveSpeed").isPresent()) {
                //mMoveSpeed = attrs.getAttr("bl_moveSpeed").get().getFloatValue();
            }
            if (attrs.getAttr("bl_indicatorSelectedSrc").isPresent()) {
                mSelectedDrawable = attrs.getAttr("bl_indicatorSelectedSrc").get().getElement();
            }

            if (attrs.getAttr("indicatorUnselectedSrc").isPresent()) {
                mUnselectedDrawable = attrs.getAttr("indicatorUnselectedSrc").get().getElement();
            }

            if (attrs.getAttr("bl_indicatorSize").isPresent()) {
                indicatorSize = attrs.getAttr("bl_indicatorSize").get().getIntegerValue();
            }

            /*int indicatorSelectedColor = Color.getIntColor("#F15C58");
            if (attrs.getAttr("bl_indicatorSelectedColor").isPresent()) {
                indicatorSelectedColor = attrs.getAttr("bl_indicatorSelectedColor").get().getColorValue().getValue();
            }*/
            if (attrs.getAttr("bl_indicatorSpace").isPresent()) {
                mIndicatorMargin = attrs.getAttr("bl_indicatorSpace").get().getDimensionValue();
            }

            if (attrs.getAttr("bl_indicatorMarginLeft").isPresent()) {
                mIndicatorMargin = attrs.getAttr("bl_indicatorMarginLeft").get().getDimensionValue();
            }
            if (attrs.getAttr("bl_indicatorMarginRight").isPresent()) {
                mIndicatorMargin = attrs.getAttr("bl_indicatorMarginRight").get().getDimensionValue();
            }
            if (attrs.getAttr("bl_indicatorMarginBottom").isPresent()) {
                mIndicatorMargin = attrs.getAttr("bl_indicatorMarginBottom").get().getDimensionValue();
            }
            initRecycleView(attrs);
        }
    }

    private void initRecycleView(AttrSet attrs) {
        if (attrs.getAttr("bl_indicatorGravity").isPresent()) {
            mIndicatorMargin = attrs.getAttr("bl_indicatorGravity").get().getDimensionValue();
        }
        if (attrs.getAttr("bl_orientation").isPresent()) {
            orientation = attrs.getAttr("bl_orientation").get().getIntegerValue();
        }
        int gravity;
        int g = 0;
        if (g == 0) {
            gravity = TableLayout.Alignment.START;
        } else if (g == DEFAULT_GRAVITY) {
            gravity = TableLayout.Alignment.END;
        } else {
            gravity = TableLayout.Alignment.BASELINE;
        }
        if (mSelectedDrawable == null) {
            ShapeElement selectedGradientDrawable = new ShapeElement();
            selectedGradientDrawable.setShape(ShapeElement.OVAL);
            selectedGradientDrawable.setCornerRadius(indicatorSize >> 1);
        }
        if (mUnselectedDrawable == null) {
            ShapeElement unSelectedGradientDrawable = new ShapeElement();
            unSelectedGradientDrawable.setShape(ShapeElement.OVAL);
            unSelectedGradientDrawable.setCornerRadius(indicatorSize >> 1);
        }

        // 轮播图部分
        mRecyclerView = new ListContainer(context);
        mRecyclerView.setOrientation(orientation);
        mRecyclerView.setReboundEffect(true);
        mRecyclerView.setReboundEffectParams(OVER_SCROLL_PERCENT, OVER_SCROLL_RATE, REMAIN_VISIBLE_PERCENT);
        StackLayout.LayoutConfig params1 = new StackLayout.LayoutConfig(ComponentContainer.LayoutConfig.MATCH_CONTENT,
            ComponentContainer.LayoutConfig.MATCH_CONTENT);
        addComponent(mRecyclerView, params1);

        // 指示器部分
        mIndicatorContainer = new ListContainer(context);
        mIndicatorContainer.setOrientation(orientation);
        mIndicatorAdapter = new IndicatorAdapter();
        mIndicatorContainer.setItemProvider(mIndicatorAdapter);
        StackLayout.LayoutConfig params = new StackLayout.LayoutConfig(ComponentContainer.LayoutConfig.MATCH_CONTENT,
            ComponentContainer.LayoutConfig.MATCH_CONTENT);
        params.alignment = TableLayout.Alignment.BOTTOM | gravity;
        params.setMargins(marginStart, 0, marginEnd, marginBottom);
        params.setMarginLeft(marginStart);
        params.setMarginRight(marginEnd);
        addComponent(mIndicatorContainer, params);
        if (!isShowIndicator) {
            mIndicatorContainer.setVisibility(HIDE);
        }
    }

    private int px2vp(float px) {
        return AttrHelper.vp2px(px, context);
    }

    /**
     * 设置是否禁止滚动播放
     *
     * @param isAutoPlaying 播放标志
     * @return 返回本对象
     */
    public BannerLayout setAutoPlaying(boolean isAutoPlaying) {
        mIsAutoPlaying = isAutoPlaying;
        setPlaying(this.mIsAutoPlaying);
        return this;
    }

    public boolean isPlaying() {
        return mIsPlaying;
    }

    /**
     * 设置是否显示指示器
     *
     * @param isCallShowIndicator 显示指示器标志
     * @return 返回本对象
     */
    public BannerLayout setShowIndicator(boolean isCallShowIndicator) {
        isShowIndicator = isCallShowIndicator;
        mIndicatorContainer.setVisibility(isCallShowIndicator ? VISIBLE : HIDE);
        return this;
    }

    /**
     * 设置当前图片缩放系数
     *
     * @param centerScale 缩放系数
     * @return 返回本对象
     */
    public BannerLayout setCenterScale(float centerScale) {
        //mCenterScale = centerScale;
        return this;
    }

    /**
     * 设置跟随手指的移动速度
     *
     * @param moveSpeed 移动速度
     * @return 返回本对象
     */
    public BannerLayout setMoveSpeed(float moveSpeed) {
        //mMoveSpeed = moveSpeed;
        return this;
    }

    /**
     * 设置图片间距
     *
     * @param itemSpace 间距
     * @return 返回本对象
     */
    public BannerLayout setItemSpace(int itemSpace) {
        //mItemSpace = itemSpace;
        return this;
    }

    /**
     * 设置轮播间隔时间
     *
     * @param autoPlayDuration 时间毫秒
     * @return 当前对象
     */
    public BannerLayout setAutoPlayDuration(int autoPlayDuration) {
        mAutoPlayDuration = autoPlayDuration;
        return this;
    }

    /**
     * 设置方向
     *
     * @param orientation 方向值
     * @return 本对象
     */
    public BannerLayout setOrientation(int orientation) {
        return this;
    }

    /**
     * 设置是否自动播放（上锁）
     *
     * @param isPlaying 开始播放
     */
    protected synchronized void setPlaying(boolean isPlaying) {
        if (mIsAutoPlaying && isHasInit) {
            if (!mIsPlaying && isPlaying) {
                mHandler.sendEvent(WHAT_AUTO_PLAY, mAutoPlayDuration);
                mIsPlaying = true;
            } else if (mIsPlaying && !isPlaying) {
                mHandler.removeEvent(WHAT_AUTO_PLAY);
                mIsPlaying = false;
            }
        }
    }

    /**
     * 设置轮播数据集
     *
     * @param adapter 适配器
     */
    public void setAdapter(BaseItemProvider adapter) {
        isHasInit = false;
        Log.i("Banner", "-----mRecyclerView is empty----" + (mRecyclerView == null));
        mRecyclerView.setItemProvider(adapter);
        mBannerSize = adapter.getCount();
        setPlaying(true);
        mRecyclerView.setScrollListener(new ListContainer.ScrollListener() {
            @Override
            public void onScrollFinished() {
                setPlaying(false);
            }
        });

        Component.ScrolledListener listener = new Component.ScrolledListener() {
            @Override
            public void scrolledStageUpdate(Component component, int newStage) {
                int first = 0;
                if (mCurrentIndex != first) {
                    mCurrentIndex = first;
                }
                if (newStage == Component.SCROLL_IDLE_STAGE) {
                    setPlaying(true);
                }
                refreshIndicator();
            }

            @Override
            public void onContentScrolled(Component component, int i, int i1, int i2, int i3) {
            }
        };
        mRecyclerView.setScrolledListener(listener);
        isHasInit = true;
    }

    /**
     * 标示点适配器
     *
     * @since 2021-04-19
     */
    protected class IndicatorAdapter extends RecycleItemProvider {
        //int currentPosition = 0;

        public void setPosition(int position) {
            //this.currentPosition = position;
        }

        @Override
        public int getCount() {
            return mBannerSize;
        }

        @Override
        public Object getItem(int i) {
            return i;
        }

        @Override
        public long getItemId(int i) {
            return i;
        }

        @Override
        public Component getComponent(int i, Component component, ComponentContainer componentContainer) {
            Image bannerPoint = new Image(getContext());
            DirectionalLayout.LayoutConfig LayoutParams = new DirectionalLayout.LayoutConfig(ComponentContainer.
                LayoutConfig.MATCH_CONTENT, ComponentContainer.LayoutConfig.MATCH_CONTENT);
            LayoutParams.setMargins(mIndicatorMargin, mIndicatorMargin, mIndicatorMargin, mIndicatorMargin);
            addComponent(bannerPoint, LayoutParams);
            return bannerPoint;
        }
    }

    /**
     * 改变导航的指示点
     */
    protected  void refreshIndicator() {
        if (mBannerSize > 1) {
            final int position = mCurrentIndex % mBannerSize;
            if (isShowIndicator) {
                mIndicatorAdapter.setPosition(position);
                mIndicatorAdapter.notifyDataChanged();
            }
            if (mOnIndicatorIndexChangedListener != null) {
                mOnIndicatorIndexChangedListener.onIndexChanged(position);
            }
        }
    }

    /**
     * banner item点击监听
     *
     * @since 2021-04-19
     */
    public interface OnBannerItemClickListener {
        /**
         * item点击回调方法
         *
         * @param position item索引
         */
        void onItemClick(int position);
    }

    /**
     * 指示器改变监听方法
     *
     * @param listener 指示器改变监听
     * @return 本对象
     */
    public BannerLayout setOnIndicatorIndexChangedListener(OnIndicatorIndexChangedListener listener) {
        mOnIndicatorIndexChangedListener = listener;
        return this;
    }

    /**
     * 索引变化监听
     *
     * @since 2021-04-19
     */
    public interface OnIndicatorIndexChangedListener {
        /**
         * 索引变化
         *
         * @param position
         */
        void onIndexChanged(int position);
    }
}
